package game;

import chess.*;

import java.util.Objects;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;

/**
 * 特殊对战模式（炮模式）
 * 负责人:
 *      张生
 */

/*
    可以单独把炮拿出来, 放在栈的顶部
    开始拿棋子一定从栈顶开始拿, 我们起始就是双方都有炮
 */

public class SpecialBattleMenu {
    private final static int ROW_NUM = 4;
    private final static int COL_NUM = 8;

    private Stack<Piece> stack = new Stack<>();
    private Random random = new Random();

    //所有棋子的定义都在这了
    private final Piece general_15 = new General(15, "帅", 30, 7, 1);
    private final Piece general_31 = new General(31, "将", 30, 7, 2);

    private final Piece warrior_14 = new Warrior(14, "士", 10, 6, 1);
    private final Piece warrior_13 = new Warrior(13, "士", 10, 6, 1);
    private final Piece warrior_30 = new Warrior(30, "仕", 10, 6, 2);
    private final Piece warrior_29 = new Warrior(29, "仕", 10, 6, 2);

    private final Piece minister_12 = new Minister(12,"相", 5, 5, 1);
    private final Piece minister_11 = new Minister(11, "相", 5, 5, 1);
    private final Piece minister_28 = new Minister(28, "象", 5, 5, 2);
    private final Piece minister_27 = new Minister(27, "象", 5, 5, 2);

    private final Piece vehicle_10 = new Vehicle(10, "车", 5, 4, 1);
    private final Piece vehicle_9 = new Vehicle(9, "车", 5, 4, 1);
    private final Piece vehicle_26 = new Vehicle(26, "車", 5, 4, 2);
    private final Piece vehicle_25 = new Vehicle(25, "車", 5, 4,2);

    private final Piece horse_8 = new Horse(8, "马", 5, 3, 1);
    private final Piece horse_7 = new Horse(7,"马", 5, 3, 1);
    private final Piece horse_24 = new Horse(24,"馬", 5, 3, 2);
    private final Piece horse_23 = new Horse(23,"馬", 5, 3, 2);

    private final Piece cannon_6 = new Cannon(6, "炮", 5, 2, 1);
    private final Piece cannon_5 = new Cannon(5,"炮", 5, 2, 1);
    private final Piece cannon_22 = new Cannon(22,"砲", 5, 2, 2);
    private final Piece cannon_21 = new Cannon(21,"砲", 5, 2, 2);

    private final Piece soldier_4 = new Soldier(4, "兵", 2, 1, 1);
    private final Piece soldier_3 = new Soldier(3,"兵", 2, 1, 1);
    private final Piece soldier_2 = new Soldier(2,"兵", 2, 1, 1);
    private final Piece soldier_1 = new Soldier(1,"兵", 2, 1, 1);
    private final Piece soldier_0 = new Soldier(0,"兵", 2, 1, 1);
    private final Piece soldier_20 = new Soldier(20,"卒", 2, 1, 2);
    private final Piece soldier_19 = new Soldier(19,"卒", 2, 1, 2);
    private final Piece soldier_18 = new Soldier(18,"卒", 2, 1, 2);
    private final Piece soldier_17 = new Soldier(17,"卒", 2, 1, 2);
    private final Piece soldier_16 = new Soldier(16,"卒", 2, 1, 2);

    //用于打乱顺序的数组(因为我们可以通过数组下标来打乱顺序), 放入栈中
    private Piece[] pieces = {
            general_15, general_31,
            warrior_14, warrior_13, warrior_30, warrior_29,
            minister_12, minister_11, minister_28, minister_27,
            vehicle_10, vehicle_9, vehicle_26, vehicle_25,
            horse_8, horse_7, horse_24, horse_23,
            soldier_4, soldier_3, soldier_2, soldier_1, soldier_0,
            soldier_20, soldier_19, soldier_18, soldier_17, soldier_16
    };

    private Piece[][] chessBoard = new Piece[ROW_NUM][COL_NUM];
    private Piece blank = new Piece(100, "〇", 0, 100, 0) {
        @Override
        public boolean isMove(Piece[][] chessBoard, int m, int n, int x, int y) {
            return false;
        }

        @Override
        public boolean isComMoveX(Piece[][] chessBoard, int x1, int y1, int x, int y) {
            return false;
        }
        @Override
        public boolean isComMoveY(Piece[][] chessBoard, int x1, int y1, int x, int y) {
            return false;
        }
    };
    private Piece nullPiece = new Piece(100, "　", 0, 100, 0) {
        @Override
        public boolean isMove(Piece[][] chessBoard, int x1, int y2, int x, int y) {
            return false;
        }

        @Override
        public boolean isComMoveX(Piece[][] chessBoard, int x1, int y1, int x, int y) {
            return false;
        }

        @Override
        public boolean isComMoveY(Piece[][] chessBoard, int x1, int y1, int x, int y) {
            return false;
        }
    };

    /**
     * 构造方法: 初始化棋盘
     */
    public SpecialBattleMenu() {
        try {
            System.out.println("开始游戏, 你作为红方");
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //把除了炮的每个棋子都转换成〇
        for (int i = 0; i < ROW_NUM; i++) {
            for (int j = 0; j < COL_NUM; j++) {
                chessBoard[i][j] = blank;
            }
        }

        //随机打乱数组中的棋子
        for (int i = 27; i >= 0; i--) {
            swap(pieces, random.nextInt(i + 1), i);
        }
        //放入栈中, 等会用于存储
        for (int i = 0; i < 28; i++) {
            stack.push(pieces[i]);
        }

        int a = random.nextInt(8);
        int b = random.nextInt(8);
        int c = random.nextInt(8);
        int d = random.nextInt(8);

        chessBoard[0][a] = cannon_5;
        chessBoard[1][b] = cannon_21;
        chessBoard[2][c] = cannon_6;
        chessBoard[3][d] = cannon_22;

    }

    /**
     * 打印棋盘
     */
    public void printBoard(){
        /*
            这里根据原形图, 还有移动过程的界面需要加上
         */
        System.out.println("---------------------------------------");
        for (int i = 0; i < ROW_NUM; i++) {
            for (int j = 0; j < COL_NUM; j++) {
                System.out.print(" | ");
                if (isRed(chessBoard[i][j].getName())) {
                    //这里用了一个改色的逻辑
                    System.out.print("\033[31m" + chessBoard[i][j].getName());
                    System.out.print("\33[0m");//恢复默认颜色
                } else {
                    System.out.print(chessBoard[i][j].getName());
                }
            }
            System.out.print(" | ");
            System.out.println();
        }
        System.out.println("---------------------------------------");
    }


    /**
     * @param s 棋子名字
     * @return 判断棋子是否要标红
     */
    private boolean isRed(String s) {
        return s.equals("帅") || s.equals("士") || s.equals("相") || s.equals("车") ||
                s.equals("马") || s.equals("炮") || s.equals("兵");
    }

    public void start() {
        Scanner scanner2 = new Scanner(System.in);
        int x = 0;
        int y = 0;
        do {
            //打印棋盘
            printBoard();
            System.out.print("请选择你的炮:>");
            x = scanner2.nextInt();
            y = scanner2.nextInt();

            //坐标不对
            if (x < 1 || x > 4 || y < 1 || y > 8) {
                System.out.println("坐标非法, 请重新输入!!!");
                continue;
            }

            if (chessBoard[x - 1][y - 1].getCategory() != 2) {
                System.out.println("只能移动炮");
                continue;
            }

            //当前位置没棋子了
            if (chessBoard[x - 1][y - 1] == nullPiece) {
                System.out.println("目标位置棋子为空, 请重新输入!");
                continue;
            }

            //已翻开的情况
            Piece tmp = chessBoard[x - 1][y - 1];
            if (tmp.getId() > 15){
                System.out.println("你不能选择对方棋子");
                continue;
            }else {
                //用户输入移动坐标
                System.out.print("请输入移动坐标:>");
                int x1 = scanner2.nextInt();
                int y1 = scanner2.nextInt();

                //判断是否可以移动
                if (tmp.isMove(chessBoard, x1, y1, x, y)){
                    Piece tmp1 = chessBoard[x1 - 1][y1 - 1];
                    chessBoard[x1 - 1][y1 - 1] = chessBoard[x - 1][y - 1];

                    //如果是炮要打未翻开棋子, 需要给这个未翻开的附上一个棋子
                    if (tmp1 == blank && chessBoard[x - 1][y - 1].getName().equals("炮")){
                        Piece tmp2 = changeChess();

                        if (tmp2.getId() < 16){
                            System.out.println("你用 " + "\033[31m" + "炮" + "\33[0m" + " 吃了 " + "\033[31m" +  tmp2.getName() + "\33[0m");
                        }else {
                            System.out.println("你用 " + "\033[31m" + "炮" + "\33[0m" + " 吃了 " + tmp2.getName());
                        }

                        //判断输赢
                        if (tmp2.getCategory() == 7){
                            if (tmp2 == general_15){
                                System.out.println("你输了！");
                            }else if (tmp2 == general_31){
                                System.out.println("你赢了！");
                            }
                            Scanner scanner = new Scanner(System.in);
                            System.out.println("按 1 重新开始 (按0退出)");
                            int k = scanner.nextInt();
                            if (k == 1){
                                new SpecialBattleMenu().start();
                            }else {
                                System.exit(0);
                            }
                        }

                    }
                    //移动就把那个原来的位置设置未null
                    chessBoard[x - 1][y - 1] = nullPiece;
                }else {
                    System.out.println("移动坐标非法");
                    continue;
                }
            }

            //电脑逻辑
            Piece piece = ComRound(chessBoard);
            if (piece.getCategory() == 7){
                gameEnd(piece);
            }
        }while (true);
    }

    /**
     * 游戏结束界面
     */
    private void gameEnd(Piece tmp2) {
        if (tmp2 == general_15){
            System.out.println("你输了！");
        }else if (tmp2 == general_31){
            System.out.println("你赢了！");
        }
        Scanner scanner = new Scanner(System.in);
        System.out.println("按 1 重新开始 (按0退出)");
        int k = scanner.nextInt();
        if (k == 1){
            new SpecialBattleMenu().start();
        }else {
            System.exit(0);
        }
    }

    /**
     * 炮模式电脑AI
     * @param chessBoard 棋盘
     */
    private Piece ComRound(Piece[][] chessBoard) {
        //
        System.out.println("---------------------------------------");
        System.out.println("电脑回合:>");

        try {
            Thread.sleep(500);//停0.5s
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //我们先考虑移动的逻辑
        return moveChess();
    }

    /**
     * 移动
     */
    private Piece moveChess() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 8; j++) {
                Piece cnt = chessBoard[i][j];
                //是电脑阵营， 并且已翻开
                if (cnt.getCamp() == 2 && cnt.getCategory() == 2){
                    Cannon cannon = (Cannon) cnt;
                    if (cannon.isSpecialComX1(chessBoard, i + 2, j, i, j)){
                        if (chessBoard[i + 2][j] == blank){
                            chessBoard[i + 2][j] = changeChess();
                        }
                        Piece tmp = chessBoard[i + 2][j];
                        chessBoard[i + 2][j] = cnt;
                        if (tmp.getId() < 16){
                            System.out.println("电脑用 " + "砲" + " 吃了 " + "\033[31m" +  tmp.getName() + "\33[0m");
                        }else {
                            System.out.println("电脑用 " + "砲" + " 吃了 " + tmp.getName());
                        }
                        chessBoard[i][j] = nullPiece;
                        if (tmp.getCategory() == 7){
                            gameEnd(tmp);
                        }
                        return tmp;
                    }else if (cannon.isSpecialComX2(chessBoard, i - 2, j, i, j)){
                        if (chessBoard[i - 2][j] == blank){
                            chessBoard[i - 2][j] = changeChess();
                        }
                        Piece tmp = chessBoard[i - 2][j];
                        chessBoard[i - 2][j] = cnt;
                        if (tmp.getId() < 16){
                            System.out.println("电脑用 " + "砲" + " 吃了 " + "\033[31m" +  tmp.getName() + "\33[0m");
                        }else {
                            System.out.println("电脑用 " + "砲" + " 吃了 " + tmp.getName());
                        }
                        chessBoard[i][j] = nullPiece;
                        if (tmp.getCategory() == 7){
                            gameEnd(tmp);
                        }
                        return tmp;
                    }else if (cannon.isSpecialComY1(chessBoard, i, j + 2, i, j)){
                        if (chessBoard[i][j + 2] == blank){
                            chessBoard[i][j + 2] = changeChess();
                        }
                        Piece tmp = chessBoard[i][j + 2];
                        chessBoard[i][j + 2] = cnt;
                        if (tmp.getId() < 16){
                            System.out.println("电脑用 " + "砲" + " 吃了 " + "\033[31m" +  tmp.getName() + "\33[0m");
                        }else {
                            System.out.println("电脑用 " + "砲" + " 吃了 " + tmp.getName());
                        }
                        chessBoard[i][j] = nullPiece;
                        if (tmp.getCategory() == 7){
                            gameEnd(tmp);
                        }
                        return tmp;
                    }else if (cannon.isSpecialComY2(chessBoard, i, j - 2, i, j)){
                        if (chessBoard[i][j - 2] == blank){
                            chessBoard[i][j - 2] = changeChess();
                        }
                        Piece tmp = chessBoard[i][j - 2];
                        chessBoard[i][j - 2] = cnt;
                        if (tmp.getId() < 16){
                            System.out.println("电脑用 " + "砲" + " 吃了 " + "\033[31m" +  tmp.getName() + "\33[0m");
                        }else {
                            System.out.println("电脑用 " + "砲" + " 吃了 " + tmp.getName());
                        }
                        chessBoard[i][j] = nullPiece;
                        if (tmp.getCategory() == 7){
                            gameEnd(tmp);
                        }
                        return tmp;
                    }
                }
            }
        }
        System.out.println("电脑用 " + "砲" + " 吃了 " + "将");
        gameEnd(general_31);
        return nullPiece;
    }


    /**
     * 随机取棋子界面
     */
    public Piece changeChess(){
        return stack.pop();
    }

    /**
     * 交换函数
     * @param pieces 数组
     * @param nextInt 随机交换值
     * @param i 被交换值
     */
    private void swap(Piece[] pieces, int nextInt, int i) {
        Piece tmp = pieces[nextInt];
        pieces[nextInt] = pieces[i];
        pieces[i] = tmp;
    }
}
